package com.example.teaching_server.service;

import com.example.teaching_server.dto.UserActivityDTO;
import com.example.teaching_server.dto.ActivityDTO;
import com.example.teaching_server.dto.CreateLaborActivityRequest;
import com.example.teaching_server.dto.ActivityListDTO;
import com.example.teaching_server.dto.DailyActivityStatusDTO;
import com.example.teaching_server.entity.*;
import com.example.teaching_server.repository.ActivityRepository;
import com.example.teaching_server.repository.ActivityCheckinRepository;
import com.example.teaching_server.repository.ActivityParticipantRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户活动管理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class UserActivityService {

    private final ActivityRepository activityRepository;
    private final ActivityCheckinRepository checkinRepository;
    private final ActivityParticipantRepository activityParticipantRepository;

    /**
     * 获取用户今天的活动及打卡信息
     */
    @Transactional(readOnly = true)
    public List<UserActivityDTO> getTodayActivities(Long userId) {
        log.debug("获取用户今天活动: userId={}", userId);

        LocalDate today = LocalDate.now();
        return getActivitiesByDate(userId, today);
    }

    /**
     * 获取用户某天已打卡的活动列表
     */
    @Transactional(readOnly = true)
    public List<UserActivityDTO> getActivitiesByDate(Long userId, LocalDate date) {
        log.debug("获取用户活动打卡信息: userId={}, date={}", userId, date);

        validateUserId(userId);
        validateDate(date);

        List<ActivityEntity> validActivities = activityRepository.findValidActivitiesByDate(userId, date);
        if (validActivities.isEmpty()) {
            log.debug("未找到用户在该日期的有效活动");
            return new ArrayList<>();
        }

        List<Long> validActivityIds = extractActivityIds(validActivities);
        List<ActivityCheckinEntity> checkins = checkinRepository.findByUserIdAndDateAndActivityIds(userId, date, validActivityIds);

        return buildUserActivityDTOs(validActivities, checkins);
    }

    /**
     * 获取用户某天所有关联活动及打卡状态
     */
    @Transactional(readOnly = true)
    public List<DailyActivityStatusDTO> getDailyActivityStatus(Long userId, LocalDate date) {
        log.debug("获取用户每日活动状态: userId={}, date={}", userId, date);

        validateUserId(userId);
        validateDate(date);

        List<ActivityEntity> validActivities = activityRepository.findValidActivitiesByDate(userId, date);
        if (validActivities.isEmpty()) {
            log.debug("未找到用户在该日期的有效活动");
            return new ArrayList<>();
        }

        List<ActivityCheckinEntity> todayCheckins = checkinRepository.findByUserIdAndDate(userId, date);
        Set<Long> checkedActivityIds = extractCheckedActivityIds(todayCheckins);

        return buildDailyActivityStatusDTOs(validActivities, checkedActivityIds);
    }

    /**
     * 获取所有活动列表，支持关键字搜索
     */
    @Transactional(readOnly = true)
    public List<ActivityListDTO> getAllActivities(Long userId, String keyword, Long baseId, String fee) {
        log.debug("获取所有活动列表: userId={}, keyword={}, baseId={}, fee={}", userId, keyword, baseId, fee);

        List<Map<String, Object>> results = activityRepository.findBySearchCriteriaWithCreatorNativeMap(keyword, baseId, fee);
        List<Long> joinedIds = activityRepository.findJoinedActivityIds(userId);

        return results.stream()
                .map(row -> convertMapToActivityListDTO(row, joinedIds))
                .collect(Collectors.toList());
    }

    /**
     * 获取用户已报名的活动列表
     */
    @Transactional(readOnly = true)
    public List<ActivityListDTO> getJoinedActivities(Long userId, String keyword, Long baseId, String fee) {
        log.debug("获取用户已报名活动: userId={}, keyword={}, baseId={}, fee={}", userId, keyword, baseId, fee);

        validateUserId(userId);

        List<Long> joinedActivityIds = activityRepository.findJoinedActivityIds(userId);
        if (joinedActivityIds.isEmpty()) {
            log.debug("用户未报名任何活动: userId={}", userId);
            return new ArrayList<>();
        }

        List<ActivityEntity> joinedActivities = activityRepository.findJoinedActivitiesWithSearch(joinedActivityIds, keyword, baseId, fee);
        return joinedActivities.stream()
                .map(this::convertActivityEntityToActivityListDTO)
                .collect(Collectors.toList());
    }

    /**
     * 获取我发布的活动列表
     */
    @Transactional(readOnly = true)
    public List<ActivityListDTO> getPublishedActivities(Long userId, String keyword, Long baseId, String fee) {
        log.debug("获取用户发布的活动: userId={}, keyword={}, baseId={}, fee={}", userId, keyword, baseId, fee);

        validateUserId(userId);

        List<ActivityEntity> publishedActivities = activityRepository.findPublishedActivitiesWithSearch(userId, keyword, baseId, fee);
        return publishedActivities.stream()
                .map(this::convertActivityEntityToActivityListDTO)
                .collect(Collectors.toList());
    }

    /**
     * 报名活动
     */
    public boolean signupActivity(Long userId, Long activityId) {
        log.info("用户报名活动: userId={}, activityId={}", userId, activityId);

        validateUserId(userId);
        validateActivityId(activityId);

        ActivityEntity activity = activityRepository.findById(activityId)
                .orElseThrow(() -> {
                    log.warn("活动不存在: activityId={}", activityId);
                    return new RuntimeException("活动不存在");
                });

        validateSignupConditions(userId, activityId, activity);

        ActivityParticipantEntity participant = createActivityParticipant(userId, activityId);
        activityParticipantRepository.save(participant);

        updateActivityParticipantCount(activity);
        return true;
    }

    /**
     * 创建新活动（劳动周专用）
     */
    public ActivityDTO createActivity(CreateLaborActivityRequest request) {
        log.info("创建劳动周活动: title={}, creatorId={}", request.getTitle(), request.getCreatorId());

        validateCreateActivityRequest(request);

        validateActivityTime(request);

        ActivityEntity activity = buildActivityEntity(request);
        ActivityEntity savedActivity = activityRepository.save(activity);

        log.info("活动创建成功: activityId={}", savedActivity.getId());
        return convertToActivityDTO(savedActivity);
    }

    /**
     * 根据活动ID获取活动详情
     */
    @Transactional(readOnly = true)
    public ActivityDTO getActivityById(Long activityId, Long userId) {
        log.debug("获取活动详情: activityId={}, userId={}", activityId, userId);

        validateActivityId(activityId);

        ActivityEntity activity = activityRepository.findById(activityId)
                .orElseThrow(() -> {
                    log.warn("活动不存在: activityId={}", activityId);
                    return new RuntimeException("活动不存在");
                });

        ActivityDTO activityDTO = convertToActivityDTO(activity);
        setCreatorInfo(activityDTO, activity);
        setUserParticipationStatus(activityDTO, userId, activityId);

        return activityDTO;
    }

    /**
     * 构建用户活动DTO列表
     */
    private List<UserActivityDTO> buildUserActivityDTOs(List<ActivityEntity> validActivities, List<ActivityCheckinEntity> checkins) {
        return checkins.stream()
                .collect(Collectors.groupingBy(checkin -> checkin.getActivity().getId()))
                .entrySet().stream()
                .map(entry -> {
                    Long activityId = entry.getKey();
                    List<ActivityCheckinEntity> activityCheckins = entry.getValue();

                    ActivityEntity activity = validActivities.stream()
                            .filter(a -> a.getId().equals(activityId))
                            .findFirst()
                            .orElse(null);

                    return activity != null ? createUserActivityDTO(activity, activityCheckins) : null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 构建每日活动状态DTO列表
     */
    private List<DailyActivityStatusDTO> buildDailyActivityStatusDTOs(List<ActivityEntity> validActivities, Set<Long> checkedActivityIds) {
        return validActivities.stream()
                .map(activity -> {
                    DailyActivityStatusDTO dto = new DailyActivityStatusDTO();
                    dto.setActivityId(activity.getId());
                    dto.setTitle(activity.getTitle());
                    dto.setStartDate(activity.getStartDate());
                    dto.setEndDate(activity.getEndDate());
                    dto.setTotalDays(activity.getTotalDays());
                    dto.setIsChecked(checkedActivityIds.contains(activity.getId()));
                    return dto;
                })
                .collect(Collectors.toList());
    }

    /**
     * 创建用户活动DTO
     */
    private UserActivityDTO createUserActivityDTO(ActivityEntity activity, List<ActivityCheckinEntity> checkins) {
        UserActivityDTO dto = new UserActivityDTO();
        dto.setActivityId(activity.getId());
        dto.setTitle(activity.getTitle());
        dto.setStartDate(activity.getStartDate());
        dto.setEndDate(activity.getEndDate());
        dto.setTotalDays(activity.getTotalDays());
        dto.setCheckedDays(checkins.size());
        dto.setChecked(!checkins.isEmpty());
        dto.setRecords(createCheckinRecordDTOs(checkins));
        return dto;
    }

    /**
     * 创建打卡记录DTO列表
     */
    private List<UserActivityDTO.CheckinRecordDTO> createCheckinRecordDTOs(List<ActivityCheckinEntity> checkins) {
        return checkins.stream()
                .map(this::createCheckinRecordDTO)
                .collect(Collectors.toList());
    }

    /**
     * 创建打卡记录DTO
     */
    private UserActivityDTO.CheckinRecordDTO createCheckinRecordDTO(ActivityCheckinEntity checkin) {
        UserActivityDTO.CheckinRecordDTO record = new UserActivityDTO.CheckinRecordDTO();
        record.setCheckDate(checkin.getCheckDate());
        record.setCheckTime(checkin.getCheckTime() != null ? checkin.getCheckTime().toString() : null);
        record.setDescription(checkin.getDescription());
        record.setImages(getCheckinImageUrls(checkin));
        return record;
    }

    /**
     * 获取打卡图片URL列表
     */
    private List<String> getCheckinImageUrls(ActivityCheckinEntity checkin) {
        return checkin.getImages() != null ?
                checkin.getImages().stream()
                        .map(ActivityCheckinImageEntity::getImageUrl)
                        .collect(Collectors.toList()) :
                Collections.emptyList();
    }

    /**
     * 将Map转换为ActivityListDTO
     */
    private ActivityListDTO convertMapToActivityListDTO(Map<String, Object> row, List<Long> joinedIds) {
        ActivityListDTO dto = new ActivityListDTO();
        dto.setId(getLong(row, "id"));
        dto.setTitle(getString(row, "title"));
        dto.setDescription(getString(row, "description"));
        dto.setStartDate(getLocalDate(row, "start_date"));
        dto.setEndDate(getLocalDate(row, "end_date"));
        dto.setTotalDays(getInteger(row, "total_days"));
        dto.setAddress(getString(row, "address"));
        dto.setStartTime(getLocalTime(row));
        dto.setRegistrationDeadline(getLocalDateTime(row, "registration_deadline"));
        dto.setTargetAudience(getString(row, "target_audience"));
        dto.setIsFree(getBoolean(row));
        dto.setPublishTime(getLocalDateTime(row, "publish_time"));
        dto.setBaseId(getLong(row, "base_id"));
        dto.setBaseName(getString(row, "base_name"));
        dto.setMaxParticipants(getInteger(row, "max_participants"));
        dto.setCurrentParticipants(getInteger(row, "current_participants"));
        dto.setCreatorId(getLong(row, "creator_id"));
        dto.setCreatorName(getString(row, "creator_name"));
        dto.setCreatorPhone(getString(row, "creator_phone"));
        dto.setCreatorEmail(getString(row, "creator_email"));
        dto.setHasJoined(joinedIds.contains(dto.getId()));
        return dto;
    }

    /**
     * 将ActivityEntity转换为ActivityListDTO
     */
    private ActivityListDTO convertActivityEntityToActivityListDTO(ActivityEntity activity) {
        ActivityListDTO dto = new ActivityListDTO();
        dto.setId(activity.getId());
        dto.setTitle(activity.getTitle());
        dto.setStartDate(activity.getStartDate());
        dto.setEndDate(activity.getEndDate());
        dto.setTotalDays(activity.getTotalDays());
        dto.setBaseId(activity.getBaseId());
        dto.setBaseName(activity.getBaseName());
        dto.setAddress(activity.getAddress());
        dto.setStartTime(activity.getStartTime());
        dto.setRegistrationDeadline(activity.getRegistrationDeadline());
        dto.setTargetAudience(activity.getTargetAudience());
        dto.setIsFree(activity.getIsFree());
        dto.setPublishTime(activity.getPublishTime());
        dto.setDescription(activity.getDescription());
        dto.setMaxParticipants(activity.getMaxParticipants());
        dto.setCurrentParticipants(activity.getCurrentParticipants());
        dto.setCreatorId(activity.getCreatorId());

        if (activity.getCreator() != null) {
            dto.setCreatorName(activity.getCreator().getName());
            dto.setCreatorPhone(activity.getCreator().getPhone());
            dto.setCreatorEmail(activity.getCreator().getEmail());
        } else {
            dto.setCreatorName("未知");
            dto.setCreatorPhone("未提供");
            dto.setCreatorEmail("未提供");
        }

        dto.setHasJoined(true);
        return dto;
    }

    /**
     * 验证报名条件
     */
    private void validateSignupConditions(Long userId, Long activityId, ActivityEntity activity) {
        boolean alreadyJoined = activityRepository.isUserJoinedActivity(userId, activityId);
        if (alreadyJoined) {
            throw new RuntimeException("您已报名此活动");
        }

        if (activity.getRegistrationDeadline() != null &&
                LocalDateTime.now().isAfter(activity.getRegistrationDeadline())) {
            throw new RuntimeException("报名已截止");
        }

        if (activity.getMaxParticipants() != null &&
                activity.getCurrentParticipants() >= activity.getMaxParticipants()) {
            throw new RuntimeException("活动人数已满");
        }
    }

    /**
     * 创建活动参与者实体
     */
    private ActivityParticipantEntity createActivityParticipant(Long userId, Long activityId) {
        ActivityParticipantEntity participant = new ActivityParticipantEntity();
        participant.setUserId(userId);
        participant.setActivityId(activityId);
        participant.setSignupTime(LocalDateTime.now());
        return participant;
    }

    /**
     * 更新活动参与人数
     */
    private void updateActivityParticipantCount(ActivityEntity activity) {
        activity.setCurrentParticipants(activity.getCurrentParticipants() + 1);
        activityRepository.save(activity);
    }

    /**
     * 构建活动实体
     */
    private ActivityEntity buildActivityEntity(CreateLaborActivityRequest request) {
        ActivityEntity activity = new ActivityEntity();
        activity.setTitle(request.getTitle());
        activity.setDescription(request.getDescription());
        activity.setBaseId(request.getBaseId());
        activity.setBaseName(request.getBaseName());
        activity.setAddress(request.getAddress());
        activity.setStartDate(request.getStartDate());
        activity.setEndDate(request.getEndDate());
        activity.setTotalDays(request.getTotalDays());
        activity.setStartTime(request.getStartTime());
        activity.setRegistrationDeadline(request.getRegistrationDeadline());
        activity.setPublishTime(request.getPublishTime() != null ? request.getPublishTime() : LocalDateTime.now());
        activity.setTargetAudience(request.getTargetAudience());
        activity.setIsFree(request.getIsFree());
        activity.setMaxParticipants(request.getMaxParticipants());
        activity.setCurrentParticipants(request.getCurrentParticipants() != null ? request.getCurrentParticipants() : 0);
        activity.setCreatorId(request.getCreatorId());
        activity.setCreatedAt(LocalDateTime.now());
        activity.setUpdatedAt(LocalDateTime.now());
        return activity;
    }

    /**
     * 设置创建人信息
     */
    private void setCreatorInfo(ActivityDTO activityDTO, ActivityEntity activity) {
        if (activity.getCreator() != null) {
            activityDTO.setCreatorName(activity.getCreator().getName());
            activityDTO.setCreatorPhone(activity.getCreator().getPhone());
            activityDTO.setCreatorEmail(activity.getCreator().getEmail());
        } else {
            activityDTO.setCreatorName("未知");
            activityDTO.setCreatorPhone("未提供");
            activityDTO.setCreatorEmail("未提供");
        }
    }

    /**
     * 设置用户参与状态
     */
    private void setUserParticipationStatus(ActivityDTO activityDTO, Long userId, Long activityId) {
        if (userId != null) {
            boolean hasJoined = activityRepository.isUserJoinedActivity(userId, activityId);
            activityDTO.setHasJoined(hasJoined);
        } else {
            activityDTO.setHasJoined(false);
        }
    }

    /**
     * 验证活动时间逻辑
     */
    private void validateActivityTime(CreateLaborActivityRequest request) {
        if (request.getStartDate() != null && request.getEndDate() != null) {
            if (request.getStartDate().isAfter(request.getEndDate())) {
                throw new RuntimeException("开始日期不能晚于结束日期");
            }
        }

        if (request.getRegistrationDeadline() != null && request.getStartDate() != null) {
            LocalDateTime startDateTime = LocalDateTime.of(request.getStartDate(),
                    request.getStartTime() != null ? request.getStartTime() : LocalTime.of(9, 0));

            if (request.getRegistrationDeadline().isAfter(startDateTime)) {
                throw new RuntimeException("报名截止时间不能晚于活动开始时间");
            }
        }

        if (request.getCurrentParticipants() != null && request.getMaxParticipants() != null) {
            if (request.getCurrentParticipants() > request.getMaxParticipants()) {
                throw new RuntimeException("当前参与人数不能超过最大参与人数");
            }
        }
    }

    // 辅助方法 - 数据类型转换
    private String getString(Map<String, Object> row, String key) {
        return row.get(key) != null ? row.get(key).toString() : null;
    }

    private Long getLong(Map<String, Object> row, String key) {
        Object value = row.get(key);
        return value != null ? ((Number) value).longValue() : null;
    }

    private Integer getInteger(Map<String, Object> row, String key) {
        Object value = row.get(key);
        return value != null ? ((Number) value).intValue() : null;
    }

    private Boolean getBoolean(Map<String, Object> row) {
        Object value = row.get("is_free");
        return value != null ? (Boolean) value : (Boolean) true;
    }

    private LocalDate getLocalDate(Map<String, Object> row, String key) {
        Object value = row.get(key);
        return value != null ? ((java.sql.Date) value).toLocalDate() : null;
    }

    private LocalDateTime getLocalDateTime(Map<String, Object> row, String key) {
        Object value = row.get(key);
        return value != null ? ((java.sql.Timestamp) value).toLocalDateTime() : null;
    }

    private LocalTime getLocalTime(Map<String, Object> row) {
        Object value = row.get("start_time");
        return value != null ? ((java.sql.Time) value).toLocalTime() : null;
    }

    // 辅助方法 - 验证
    private void validateUserId(Long userId) {
        if (userId == null || userId <= 0) {
            throw new IllegalArgumentException("用户ID无效");
        }
    }

    private void validateDate(LocalDate date) {
        if (date == null) {
            throw new IllegalArgumentException("日期不能为空");
        }
    }

    private void validateActivityId(Long activityId) {
        if (activityId == null || activityId <= 0) {
            throw new IllegalArgumentException("活动ID无效");
        }
    }

    private void validateCreateActivityRequest(CreateLaborActivityRequest request) {
        if (request == null) {
            throw new IllegalArgumentException("请求参数不能为空");
        }
        if (request.getCreatorId() == null || request.getCreatorId() <= 0) {
            throw new IllegalArgumentException("创建者ID无效");
        }
        if (request.getTitle() == null || request.getTitle().trim().isEmpty()) {
            throw new IllegalArgumentException("活动标题不能为空");
        }
    }

    // 辅助方法 - 数据提取
    private List<Long> extractActivityIds(List<ActivityEntity> activities) {
        return activities.stream()
                .map(ActivityEntity::getId)
                .collect(Collectors.toList());
    }

    private Set<Long> extractCheckedActivityIds(List<ActivityCheckinEntity> checkins) {
        return checkins.stream()
                .map(checkin -> checkin.getActivity().getId())
                .collect(Collectors.toSet());
    }

    // 辅助方法 - 实体转换
    private ActivityDTO convertToActivityDTO(ActivityEntity activity) {
        ActivityDTO dto = new ActivityDTO();
        dto.setId(activity.getId());
        dto.setTitle(activity.getTitle());
        dto.setDescription(activity.getDescription());
        dto.setBaseId(activity.getBaseId());
        dto.setBaseName(activity.getBaseName());
        dto.setAddress(activity.getAddress());
        dto.setStartDate(activity.getStartDate());
        dto.setEndDate(activity.getEndDate());
        dto.setTotalDays(activity.getTotalDays());
        dto.setStartTime(activity.getStartTime());
        dto.setRegistrationDeadline(activity.getRegistrationDeadline());
        dto.setPublishTime(activity.getPublishTime());
        dto.setTargetAudience(activity.getTargetAudience());
        dto.setIsFree(activity.getIsFree());
        dto.setMaxParticipants(activity.getMaxParticipants());
        dto.setCurrentParticipants(activity.getCurrentParticipants());
        dto.setCreatorId(activity.getCreatorId());
        dto.setCreatedAt(activity.getCreatedAt());
        dto.setUpdatedAt(activity.getUpdatedAt());
        return dto;
    }
}
